package semantic_compute.concept_identify.yago_identify;

import com.orientechnologies.orient.core.sql.OCommandSQL;
import com.tinkerpop.blueprints.Vertex;
import com.tinkerpop.blueprints.impls.orient.OrientGraph;
import common.dao.orient.OrientGraphDao;
import common.dao.orient.OrientJDBCDao;
import javafx.util.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import semantic_compute.common.yago_helper.YagoLuceneQueryer;
import semantic_compute.common.yago_helper.YagoQueryHelper;
import semantic_compute.common.yago_schema.MatchedVertexItem;
import semantic_compute.common.yago_schema.LuceneItem;
import semantic_compute.entity_linking.schema.EntityLinkingResult;

import java.sql.Connection;
import java.util.*;

/**
 * Created by julianzliu on 4/17/2017.
 */
public class YagoConceptIdentifier {

    static final Logger logger = LoggerFactory.getLogger(YagoConceptIdentifier.class);


    private OrientJDBCDao orientJDBCDao;
    private Connection connection;

    private OrientGraphDao orientGraphDao;
    private OrientGraph orientGraph;

    private YagoLuceneQueryer luceneQueryer;


    public final Integer threshold = 10; //每个查询只返回排序靠前的10条记录


    public YagoConceptIdentifier(){
        this.orientJDBCDao = new OrientJDBCDao();
        this.connection  =this.orientJDBCDao.getConn();

        this.orientGraphDao = new OrientGraphDao();
        this.orientGraph = this.orientGraphDao.getGraph();

        this.luceneQueryer = new YagoLuceneQueryer();
    }






    /***********************************************************
     *
     * @param phrase
     * 返回文本匹配的类 （rid, yago_id, indegree, {label_set} ）
     */
    public  List<MatchedVertexItem> getIndgreeSortedResult(String phrase){
        String query = YagoQueryHelper.phraseToQuery(phrase);
        logger.info("[getIndgreeSortedResult] query_string = {}", query);
        String sql = String.format(
                          "select @rid as rid, yago_id as yid, inE().asList().size() as in_size ,out() from (" + "\n"
                        + "  select from ( " + "\n"
                        + "    select expand(in()) from (" + "\n"
                        + "      select *"   + "\n"
                        + "         from YAGO_LABEL_CLASS"     + "\n"
                        + "         where yago_label LUCENE \"%s\"" + "\n"
                        + "       )" + "\n"
                        + "   )" + "\n"
                        + "    where yago_type = 'CONCEPT' " + "\n"
                        + " )" + "\n"
                ,query
        );
        logger.info("[getIndgreeSortedResult] sql = \n{}" , sql);
        Iterable<Vertex> vertices = (Iterable<Vertex>) this.orientGraph.command(
                new OCommandSQL(sql )
        ).execute();


        List<MatchedVertexItem> matchedVertexItems = new ArrayList<>();
        //Map<String, Integer>  yago_concept_indegree = new HashMap<>();
        for(Vertex row: vertices){
            MatchedVertexItem matchedVertexItem = new MatchedVertexItem();
            Integer in_size = row.getProperty("in_size");
            String yago_id = row.getProperty("yid");
            String rid = YagoQueryHelper.getRidOfVertex(  (Vertex)row.getProperty("rid")  );
            matchedVertexItem.yago_id = yago_id;
            matchedVertexItem.rid = rid;
            matchedVertexItem.indegree = in_size;
            //System.out.println("in_size=" + in_size + " , yago_id = " + yago_id + " , rid = " + rid);
            Iterable<Vertex> out_vertexs = row.getProperty("out");
            for(Vertex out_vertex: out_vertexs){
                matchedVertexItem.out_rids.add( YagoQueryHelper.getRidOfVertex(out_vertex) );
            }
            matchedVertexItems.add(matchedVertexItem);
            //yago_concept_indegree.put(yago_id, in_size);
        }
        //return yago_concept_indegree;
        return matchedVertexItems;
    }


    private Double getSimpleConceptScore(Integer indgree, Float lucene_score){
        /*
        排序公式
         */
        Double final_score = Math.log(indgree + 2) * lucene_score;
        return final_score;
    }



    public List<Pair<String, Double>> simpleConceptIdentify(String phrase) {
        /*
        查询包含 text 中所有关键词的Label 对应的 概念
         */
        List<MatchedVertexItem> concepts = getIndgreeSortedResult( phrase );
        Map<String, LuceneItem>   concept_scores = this.luceneQueryer.getLuceneSortedResultForConcept(phrase);

        TreeMap<Double, String> final_scores = new TreeMap<>(Collections.reverseOrder());

        for(MatchedVertexItem matchedVertexItem : concepts){
            for(String rid: matchedVertexItem.out_rids){
                if(concept_scores.containsKey(rid) ) {
                    LuceneItem luceneItem = concept_scores.get(rid);
                    Float normalize_score = luceneItem.getNormalizeScore();
                    if (normalize_score > matchedVertexItem.lucene_score)
                        matchedVertexItem.lucene_score = normalize_score;
                }
            }
            Double final_score = getSimpleConceptScore(matchedVertexItem.indegree, matchedVertexItem.lucene_score);
            System.out.println("[yago_id = " +  matchedVertexItem.yago_id + " , lucene_score = " + matchedVertexItem.lucene_score + " , indgree = " + matchedVertexItem.indegree + "]");
            final_scores.put(final_score, matchedVertexItem.yago_id);
        }

        List<Pair<String,Double>> rankList = new ArrayList<>();
        for(Double score: final_scores.keySet()){
            rankList.add( new Pair<>(final_scores.get(score), score));
        }
        return rankList;
    }









    public void advanceConceptIdentify(String text){



    }

    public void advanceConceptIdentify(String text, EntityLinkingResult entityLinkingResult){

    }



    /**********************************************************************************
     * MAIN
     * @param args
     */
    public static void main(String[] args){
        String phrase = "president";
        if(args.length > 0){
            phrase = "";
            for(String token:args) phrase += " " + token;
        }
        YagoConceptIdentifier identifier = new YagoConceptIdentifier();
        /*
        Map<String, Float> score_list = identifier.getLuceneSortedResultForConcept(phrase);
        System.out.println("\n\n\n\nLucene Query Result-----------------");
        for(String yago_id:score_list.keySet()){
            System.out.println("yago_id = " + yago_id + " , score = " + score_list.get(yago_id));
        }
        */
        List<Pair<String, Double>> rankList = identifier.simpleConceptIdentify(phrase);
        System.out.println("\n\n\n\nLucene Query Result-----------------");
        for(Pair<String,Double> pair:rankList){
            System.out.println(" yago_id = " + pair.getKey() + " , score = " + pair.getValue());
        }
    }


}
